/*
 * Copyright (c) Meta Platforms, Inc. and affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

#include <stdint.h>
#include <stdio.h>
#include <cstring>
#include <fstream>
#include <iostream>
#include <sstream>
#include <stdexcept>
#include <unordered_map>

#include "se_defines.h"

SE_GLOBALS()

class FormatError : public std::runtime_error {
 public:
  explicit FormatError(std::string f) : std::runtime_error(f) {}
};

class Reader {
 public:
  std::string data;
  size_t offset;
  Reader(std::string str) : data(str), offset(0) {}

  uint32_t read_u32() {
    uint32_t res = 0;
    std::string raw_bytes = data.substr(offset, 4);
    if (raw_bytes.size() != 4) {
      throw FormatError("couldn't read u32");
    }
    std::memcpy(&res, raw_bytes.c_str(), 4);
    offset += 4;
    return res;
  }

  std::string read_str(uint32_t len) {
    std::string res = data.substr(offset, len);
    if (res.size() != len) {
      throw FormatError("couldn't read string");
    }
    offset += len;
    return res;
  }
};

std::string parse_msg(std::string str) {
  Reader rd(str);
  if (rd.read_u32() != 0xC0DEC0DE) {
    throw FormatError("wrong_magic");
  }
  SE_STEP(true);
  if (rd.read_str(rd.read_u32()) != "msg_type") {
    throw FormatError("wrong_msg_type");
  }
  return rd.read_str(rd.read_u32());
}

bool test_case(std::string str) {
  try {
    std::string msg = parse_msg(str);
    if (msg == "file_content") {
      SE_TARGET_STATE(true);
    }
  } catch (FormatError& e) {
    std::cerr << "Error: " << e.what() << "\n";
    return false;
  }
  return true;
}

int main(int argc, char* argv[]) {
  std::istream* input;
  std::ifstream file;
  if (argc < 2) {
    input = &std::cin; // No file name provided, read from stdin
  } else {
    file.open(argv[1]);
    if (!file) {
      std::cerr << "Could not open the file.\n";
      return 1;
    }
    input = &file; // File opened successfully, read from file
  }
  std::string content(
      (std::istreambuf_iterator<char>(*input)),
      std::istreambuf_iterator<char>());
  test_case(content);
  return 0;
}
